package oop.ex2.tools;

import java.io.IOException;
import java.util.regex.*;
import oop.ex2.main.*;


/**
 * @author yossavi
 *
 */
public class TextProcessor {
	
	String line,sign="";
	
	/**
	 * Constructor
	 * @param line- the text to process
	 */
	public TextProcessor(String line) {
		this.line=line;
	}

	/**
	 * return the next word that separate by the "separator"
	 * if the separator not found will throw UnknownStatementException
	 * @param separator- the separate char
	 * @return the text before "separator"
	 * @throws UnknownStatementException 
	 */
	public String findNextSeparatedBy (String separator) throws UnknownStatementException {
		Pattern pattern = Pattern.compile(".+?"+separator);
		Matcher matcher = pattern.matcher(this.line);
		if (matcher.find()) {
			String found=this.line.substring(matcher.start(), matcher.end()-1);
			this.sign=String.valueOf(line.charAt(matcher.end()-1));
			this.line=line.substring(matcher.end(), line.length());
			return found;
		}
		throw new UnknownStatementException("UnKnown command");
	}
	
	/**
	 * return the next string that separate by special sign  =;(){},
	 * if there is no sign will return the rest of the text
	 * @return the text before the next sign
	 */
	public String findNextWord () {
		try {
			return findNextSeparatedBy ("[ =;\\(\\)\\{\\},]");
		} catch (Exception e) {
			return getLine();
		}
	}
	
	/**
	 * return the last separator
	 * @return the last separator
	 */
	public String getSeparatedSign () {
		return this.sign;
	}
	
	/**
	 * return the rest of the text
	 * @return the rest of the text
	 */
	public String getLine () {
		if (this.line==null || this.line.isEmpty())
			return null;
		String line=this.line;
		this.line=null;
		return line;
	}
	
	/**
	 * clean the code from spaces tabs and comments
	 * @throws IOException
	 * @throws UnClosedStatementException 
	 */
	public static void cleanCode () throws IOException, UnClosedStatementException {
		if (Sjavac.line==null)
			return;
		TextProcessor.RemoveSpaces();
		TextProcessor.removeSpecialSpaces();
		TextProcessor.removeComments();
		if (Sjavac.line==null)
			return;
		if (CheckType.isEmpty(Sjavac.line)) {
			Sjavac.nextLine();
			cleanCode();
		}
	}
	
	/**
	 * replaces every spaces and tabs with one space
	 * remove the first and last space
	 */
	public static void RemoveSpaces() {
		// Remove not informative spaces and tabs
		Sjavac.line=Sjavac.line.replaceAll("\\s+", " ");
		Sjavac.line=Sjavac.line.trim();
	}
	
	/**
	 * removes any not informative spaces
	 */
	public static void removeSpecialSpaces () {
		Pattern pattern = Pattern.compile("(.*?)( ?([=;\\(\\)\\{\\},]) ?)");
		Matcher matcher = pattern.matcher(Sjavac.line);
		boolean isMattch=matcher.find();
		while (isMattch) {
			Sjavac.line=matcher.replaceAll("$1$3");
			isMattch=matcher.find();
		}
		
	}
	
	/**
	 * removes any comments
	 * @throws IOException
	 * @throws UnClosedStatementException 
	 */
	public static void removeComments () throws IOException, UnClosedStatementException {
		
		if (Sjavac.line==null)
			return;
		Pattern pattern = Pattern.compile("(.*?)(//)(.*)");
		Matcher matcher = pattern.matcher(Sjavac.line);
		if(matcher.find()) {
			Sjavac.line=matcher.group(1);
			return;
		}

		pattern = Pattern.compile("(.*?)(/\\*)(.*)");
		Matcher OpenMatcher = pattern.matcher(Sjavac.line);
		if(OpenMatcher.find()) {
			String before=OpenMatcher.group(1);
			boolean isCloesd=false;
			
			while (Sjavac.line!=null) {
				pattern = Pattern.compile("(.*?)(\\*/)(.*)");
				Matcher CloseMatcher = pattern.matcher(Sjavac.line);
				if (CloseMatcher.find()) {
					isCloesd=true;
					Sjavac.line=before+" "+CloseMatcher.group(3);
					removeComments();
					break;
				}
				before="";
				Sjavac.nextLine();
			}
			if (!isCloesd)
				throw new UnClosedStatementException("Uncloesd multi lines comments");
		}
	}
	
	/**
	 * remove the last char in the line
	 * @param line- the line to remove the char
	 * @return the line without the last char
	 */
	public static String removeLast (String line) {
		return line.substring(0, line.length()-1);
	}
	
}
